// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright © 2018-2019 Ariadne Devos
/* sHT -- connect to the Internet via Unix APIs */

#include "fd.h"

#include <sHT/compiler.h>
#include <sHT/test.h>

#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>

static const int sHT_true = 1;

static int
sHT_enable_sockopt(int fd, int layer, int flag)
{
	return setsockopt(fd, layer, flag, &sHT_true, sizeof(sHT_true));
}

int
sHT_passive_ipv6(const struct sHT_passive_in6 *in)
{
	int fd = socket(AF_INET6, in->type, 0);
	if (sHT_lt0(fd))
		return -errno;
	int ret = sHT_enable_sockopt(fd, IPPROTO_IP, IP_FREEBIND);
	if (sHT_nonzero_p(ret))
		goto socket;
	ret = sHT_enable_sockopt(fd, SOL_SOCKET, SO_REUSEPORT);
	if (sHT_nonzero_p(ret))
		goto socket;
	/* XXX SO_ATTACH_BPF (seccomp filtering) */
	ret = bind(fd, (struct sockaddr *) &in->addr, sizeof(in->addr));
	if (sHT_lt0(ret))
		goto socket;
	ret = listen(fd, in->backlog);
	if (sHT_lt0(ret))
		goto socket;
	return fd;

socket:
	ret = -errno;
	sHT_close(fd);
	return ret;
}
